/**
 * 
 */
package com.oron3.bouncer.genericgl;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import java.util.ArrayList;

import javax.microedition.khronos.opengles.GL10;

import com.oron3.bouncer.objects.shapes.PPoint;
import com.oron3.bouncer.objects.shapes.Point;

/**
 * @author Ofek
 *
 */
public class GL3D {
	public final ArrayList<Short> indices = new ArrayList<Short>();
	public final ArrayList<Point> points = new ArrayList<Point>();
	public ShortBuffer mIndexBuffer;
	public FloatBuffer mVertexBuffer;

	public float[] getPoints() {
		final float[] floats = new float[points.size() * 3];
		int i = 0;
		for (final Point p : points) {
			floats[i++] = p.x;
			floats[i++] = p.y;
			floats[i++] = p.z;
		}
		return floats;
	}

	public short[] getIndices() {
		final short[] bytes = new short[indices.size()];
		int i = 0;
		for (final short b : indices) {
			bytes[i++] = b;
		}
		return bytes;
	}

	/**
	 * @param cPoint
	 */
	public void add(final Point... cPoints) {
		for (final Point c : cPoints) {
			points.add(c);
		}
	}

	public void add(final PPoint... pPoints) {
		for (final PPoint p : pPoints) {
			points.add(p.toCartesian());
		}
	}

	/**
	 */
	public void add(final int... indices) {
		for (final int p : indices) {
			this.indices.add((short) p);
		}
	}

	/**
	 * 
	 */
	public void createIndicesBuffer() {
		if ( indices.size() == 0 ) return; 
		final ByteBuffer allocateDirect = ByteBuffer.allocateDirect(indices.size() * 4);
		allocateDirect.order(ByteOrder.nativeOrder());
		mIndexBuffer = allocateDirect.asShortBuffer();
		mIndexBuffer.put(getIndices());
		mIndexBuffer.position(0);
	}

	public void createPointsBuffer() {
		final ByteBuffer vbb = ByteBuffer.allocateDirect(points.size() * 4 * 3);
		vbb.order(ByteOrder.nativeOrder());
		mVertexBuffer = vbb.asFloatBuffer();
		mVertexBuffer.put(getPoints());
		mVertexBuffer.position(0);
	}

	public void prepare() {
		createPointsBuffer();
		createIndicesBuffer();
	}

	/**
	 * @param gl
	 */
	public void draw(final GL10 gl, final int gl_type) {
		mVertexBuffer.position(0);
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);
		if (indices.size() > 0) {
			mIndexBuffer.position(0);
			gl.glDrawElements(gl_type, indices.size(), MatrixTrackingGL.GL_UNSIGNED_SHORT, mIndexBuffer);	
		}
		else
			gl.glDrawArrays(gl_type, 0, points.size());
		gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
	}
}
